import axios from "axios";
import { Loading, Message } from "element-ui";
import Qs from "qs";

export const REQUEST_TYPE = {
  GET: "get",
  GET_PATH: "getPath",
  POST: "post",
  POST_FORM_DATA: "postFormData",
  POST_JSON: "postJson",
  DELETE: "delete",
  PATCH: "patch",
  PUT: "put",
  PUT_JSON: "putJson",
  DOWNLOAD: "download",
  DOWNLOAD_POST: "download_POST",
  DELETE_JSON: "deleteJson",
  DOWNLOAD_POST_BLOB: "download_POST_blob"
};

const service = axios.create({
  baseURL: "", // 请求base_url
  timeout:  6000000000, // 超时时间
  withCredentials: true // 携带cookie
});

// request拦截器
service.interceptors.request.use(
  (config) => {

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// response 拦截器
service.interceptors.response.use(
  (response) => {
    let res;
    if (response.data.data) {
      res = response.data.data;
    } else if (response.data) {
      res = response.data;
    } else {
      res = response;
    }
    if (res.code && typeof res.code === "number" && res.code !== 200) {
      return Promise.reject(res);
    } else if (res.code === 503) {
      return Promise.reject(res);
    } else {
      return res;
    }
  },
  (error) => {
    return Promise.reject(error);
  }
);

/**
 * 公共请求方法
 * @param option 请求参数对象
 * @param option.method 请求方式
 * @param option.url 请求url
 * @param option.data 请求传参
 * @param option.isParams 是否将请求参数拼接在url上
 * @param option.isData 是否将请求参数拼接在url上
 * @param option.cancelToken 取消请求
 * @param bol 是否开启全局loading
 * @param log 请求报错是否自动弹窗
 * @returns {Promise<*>}
 */
async function request(option, bol = false, log = true) {
  const queryTypeMap = {
    [REQUEST_TYPE.GET]: () => service.get(
      option.url,
      {
        cancelToken: option.cancelToken,
        params: option.data /* get第二个参数是一个对象，这个对象的params是一个参数对象 */
      }
    ),
    [REQUEST_TYPE.POST]: () => service.post(
      option.url,
      option.isParams ? null : Qs.stringify(option.data),
      {
        cancelToken: option.cancelToken,
        params: !option.isParams ? null : option.data
      }
    ),
    [REQUEST_TYPE.POST_FORM_DATA]: () => service.post(
      option.url,
      option.data,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "multipart/form-data" }
      }
    ),
    [REQUEST_TYPE.POST_JSON]: () => service.post(
      option.url,
      option.isParams ? null : option.data,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "application/json" },
        params: !option.isParams ? null : option.data
      }),
    [REQUEST_TYPE.DOWNLOAD_POST]: () => service.post(
      option.url,
      option.isParams ? null : option.data,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "application/json" },
        params: !option.isParams ? null : option.data,
        responseType: "arraybuffer",
        timeout: 900000
      }),
    [REQUEST_TYPE.DOWNLOAD_POST_BLOB]: () => service.post(
      option.url,
      option.isParams ? null : option.data,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "application/json" },
        params: !option.isParams ? null : option.data,
        responseType: "blob",
        timeout: 900000
      }),
    [REQUEST_TYPE.DELETE]: () => service.delete(
      option.url,
      {
        cancelToken: option.cancelToken,
        params: option.data
      }
    ),
    [REQUEST_TYPE.DELETE_JSON]: () => service.delete(
      option.url,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "application/json" },
        data: option.data
      }
    ),
    [REQUEST_TYPE.PATCH]: () => service.patch(
      option.url,
      option.data,
      {
        cancelToken: option.cancelToken
      }
    ),
    [REQUEST_TYPE.PUT]: () => service.put(
      option.url,
      option.data,
      { cancelToken: option.cancelToken }
    ),
    [REQUEST_TYPE.PUT_JSON]: () => service.put(
      option.url,
      option.data,
      {
        cancelToken: option.cancelToken,
        headers: { "Content-Type": "application/json" }
      }
    ),
    [REQUEST_TYPE.DOWNLOAD]: () => service({
      method: "get",
      url: option.url,
      data: option.data,
      responseType: "blob",
      cancelToken: option.cancelToken
    })

  };
  // 全局loading单例
  let loadingInstance;
  try {
    if (bol) {
      loadingInstance = Loading.service({
        lock: true,
        text: "加载中...",
        background: "rgba(0, 0, 0, 0.7)"
      });
    }
    return await queryTypeMap[option.method]();
  } catch (e) {
    if (log) {
      const { msg, message } = e;
      if (msg) {
        Message.error(msg.length < 100 ? msg : "请求异常，请联系管理人员");
      } else if (message.includes("操作频率过快")) {
        console.warn(e);
      } else if (message) {
        if (message.includes("timeout of")) {
          Message.error("查询超时，请重新查询！");
        } else {
          Message.error(message.length < 100 ? message : "请求异常，请联系管理人员");
        }
      }
    }
    throw e;
  } finally {
    if (bol && loadingInstance) {
      loadingInstance.close();
    }
  }
}

export default request;
